package com.yootk.gateway.filter.global;

import com.alibaba.nacos.api.utils.StringUtils;
import com.yootk.gateway.config.GatewayJWTConfigProperties;
import com.yootk.jwt.code.JWTResponseCode;
import com.yootk.jwt.service.ITokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

@Component
@Slf4j
public class JWTTokenCheckFilter implements GlobalFilter {  // 全局过滤器
    @Autowired
    private GatewayJWTConfigProperties jwtConfig; // JWT的相关配置属性
    @Autowired
    private ITokenService tokenService; // 进行Token处理
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getURI().getPath(); // 获取路径
        if (this.jwtConfig.getSkipAuthUrls() != null && this.jwtConfig.getSkipAuthUrls().contains(url)) {
            return chain.filter(exchange); // 向下继续执行其他的后续操作
        }
        // 网关将通过头信息获取到JWT的数据内容，网关技术通过WebFlux技术开发的
        String token = null;
        try{
            token = exchange.getRequest().getHeaders().get(this.jwtConfig.getHeaderName()).get(0);
        } catch (Exception e){}
        log.info("网关Token检查，Token = {}", token); // 日志输出
        // 如果假设Token有错误了，那么网关是需要直接进行响应的，请求肯定不会发送给目标的微服务
        ServerHttpResponse response = exchange.getResponse();
        if (StringUtils.isBlank(token)) { // Token数据为空
            DataBuffer buffer = response.bufferFactory().wrap(JWTResponseCode.NO_AUTH_CODE.toString().getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Flux.just(buffer)); // 异步响应错误
        } else {    // Token数据不为空
            if (this.tokenService.verifyToken(token)) { // 校验成功
                return chain.filter(exchange);
            } else {
                DataBuffer buffer = response.bufferFactory().wrap(JWTResponseCode.TOKEN_TIMEOUT_CODE.toString().getBytes(StandardCharsets.UTF_8));
                return response.writeWith(Flux.just(buffer)); // 异步响应错误
            }
        }
    }
}
